package xijia.meilisearch.service.impl;


import cn.hutool.db.Entity;
import cn.hutool.http.HtmlUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSON;
import com.meilisearch.sdk.*;
import com.meilisearch.sdk.model.FacetSearchable;
import com.meilisearch.sdk.model.SearchResult;
import com.meilisearch.sdk.model.Searchable;
import com.meilisearch.sdk.model.Settings;
import org.springframework.stereotype.Service;
import xijia.meilisearch.service.MeiLiSearchService;
import xijia.meilisearch.service.conts.MeilisearchConts;
import xijia.meilisearch.util.TokenizerUtil;

import java.util.HashMap;
import java.util.List;

@Service
public class MeiLiSearchServiceImpl implements MeiLiSearchService {
    @Override
    public boolean addDbDataDocuments() {

        // 获取配置
        Client client = new Client(new Config(MeilisearchConts.baseUrl, MeilisearchConts.apikey));
        client.deleteIndex("xijia-plus-doc");

        //  创建文档索引
        Index index = client.index("xijia-plus-doc");

        // 读取数据
        ExcelReader reader = ExcelUtil.getReader("t_doc_info2.xlsx");
        List<HashMap> entities = reader.readAll(HashMap.class);

        entities.forEach(entity -> {

            // 增加额外分词开始
            Object name = entity.get("name");
            Object contentHtml = entity.get("content_html");
            if (name != null) {
                String nameStr = entity.get("name").toString();
                entity.put("name_zh", TokenizerUtil.parse(nameStr));
            }
            if (contentHtml != null) {
                String contentHtmlStr = entity.get("content_html").toString();
                contentHtmlStr = HtmlUtil.cleanHtmlTag(contentHtmlStr);
                entity.put("content_html", contentHtmlStr);
                entity.put("content_zh", TokenizerUtil.parse(contentHtmlStr));
            }
        });
        // 增加额外分词结束

        String dataJsonStr = JSON.toJSONString(entities);
        // 添加文档
        index.addDocuments(dataJsonStr, "id");
        return true;
    }

    @Override
    public boolean initRules() {
        Client client = new Client(new Config(MeilisearchConts.baseUrl, MeilisearchConts.apikey));
        Settings settings = new Settings();
        // 自定义排名规则, 先以下定义的优先级进行排序, 在根据具体的数据在此排序
        // 如下, 先根据搜索词在文档中出现的字段 attribute 字段排序，在根据查询搜索时指定的 sort 排序字段排序, 在根据搜索词匹配情况排序...
        // https://www.meilisearch.com/docs/learn/relevancy/ranking_rules
        settings.setRankingRules(new String[]
                {
                        "attribute",  //  搜索词在文档中出现的字段来决定优先级, 通过 setSearchableAttributes
                        "sort",       //  查询中指定的排序参数,如: price: asc, 价格升序 // 足球 1 2 3  |  name:asc
                        "exactness",  //  搜索词完全匹配情况, 匹配次越完全, 排名越高
                        "words",      //  搜索词的匹配程度来排序 (分词匹配/模糊匹配), 匹配词越多, 匹配越完整的文档排名会越高
                        "typo",       //  拼写错误的数量来排序， 拼写更精确、错误更少的文档会排名越高
                        "proximity"   //  相邻词, 如: quick brown fox ,文档中这几个词相邻的排名会高于这几个词不相邻的
                });

        // 设置可搜索字段
        // 字段的顺序也间接影响了优先级, 靠前的字段会被优先搜索, 匹配到的结果会有更高的权重，根据 setRankingRules 设置字段排序优先级
        settings.setSearchableAttributes(new String[]{"name", "content"});

        // 设置可排序字段
        settings.setSortableAttributes(new String[]{"sort", "create_time"});
        // 设置过滤条件的可搜索字段, 搜索字段也可用于分组 (分面设置) xxx=xxx
        settings.setFilterableAttributes(new String[]{"author", "id"});
        // 设置响应字段, 可以查询时在指定
        // settings.setDisplayedAttributes(new String[]{"xxx"});
        // 设置
        client.index("xijia-plus-doc").updateSettings(settings);
        // 等待任务完成
        System.out.println("初始化 " + "xijia-plus-doc" + " 文档的规则完成");
        return true;
    }

    // 简单查询
    @Override
    public SearchResult search(String keyword) {
        Client client = new Client(new Config(MeilisearchConts.baseUrl, MeilisearchConts.apikey));
        Index index = client.index("xijia-plus-doc");
        SearchResult search = index.search(keyword);
        return search;
    }

    // 1、分页搜索/最大限制
    @Override
    public Searchable searchTwo(String keyword) {

        Client client = new Client(new Config(MeilisearchConts.baseUrl, MeilisearchConts.apikey));
        Index index = client.index("xijia-plus-doc");
        SearchRequest searchRequest = new SearchRequest(keyword)
                .setShowMatchesPosition(false)    // 显示匹配项位置
                .setLimit(1000)         // 查询最大限制
                .setPage(1)          // 页数
                .setHitsPerPage(10);   // 条数

        // 设置搜索字段
        searchRequest.setAttributesToSearchOn(new String[]{"name", "content"});

        // 设置响应字段
        // searchRequest.setAttributesToRetrieve(new String[]{"id","name"});

        // 高亮显示的匹配词
//        searchRequest.setAttributesToHighlight(new String[]{"name", "content"})
//                // 高亮标记开始
//                .setHighlightPreTag("<span class=\"ms-highlight\">")
//                // 高亮标记结束
//                .setHighlightPostTag("</span>");

        // sort 规则下的字段排序
        // 排序字段
        // searchRequest.setSort(new String[]{"sort:desc"});

        // 过滤条件
        // searchRequest.setFilter(new String[]{"author='兮家小二' AND id='1655742648417304577'"});

        // searchRequest.setFacets(new String[]{"author"});

        Searchable search = index.search(searchRequest);
        return search;
    }

// 自定义分词后的高亮处理
// 分词后的keys
//    String parse = TokenizerUtil.parse(keyword);
    // 高亮处理
//        String[] keys = keyword.split(" ");
//        for (String key : keys) {
//            "".replaceAll(key,"<span class=\"ms-highlight\">"+key+"</span>");
//        }


    @Override
    public FacetSearchable facetSearch(String keyword) {
        Client client = new Client(new Config(MeilisearchConts.baseUrl, MeilisearchConts.apikey));
        Index index = client.index("xijia-plus-doc");
        FacetSearchRequest fsr = FacetSearchRequest.builder()
                .q(keyword)           // 搜索词
                .facetName("author")   // 分组字段
                .facetQuery("")       // 子查询条件
                .attributesToSearchOn(new String[]{"name", "content"})
                .build();
        FacetSearchable facetSearchable = index.facetSearch(fsr);
        return facetSearchable;
    }
}
